/**
 * ZHU framework. Copyright 2012-, all rights reserved.
 *
 * $Id: DailyServiceImpl.java 36 2012-08-31 03:02:52Z zhuxiaopeng $
 * $Revision: 36 $
 * $Date: 2012-08-31 11:02:52 +0800 (五, 2012-08-31) $
 * $Author: zhuxiaopeng $
 */
package daily.service;

import java.util.*;

import javax.ejb.*;
import javax.persistence.*;

import zhu.framework.service.*;

import com.google.common.collect.*;

import daily.entity.*;
import daily.entity.security.*;
import daily.util.*;

/**
 * <p>
 * </p>
 * 
 * @author $Author: zhuxiaopeng $
 * @version $Revision: 36 $ - $Date: 2012-08-31 11:02:52 +0800 (五, 2012-08-31) $
 */
@Stateless
public class DailyServiceImpl extends AbstractPersistenceOperationService {

	public List<DailyData> getDailyByDay(final Staff loginStaff, final List<Staff> staffs) {
		final List<DailyData> dailyList = Lists.newArrayList();
		final Date day = new Date();
		final SecurityRole securityRole = getSecurityRole(loginStaff, Function.DAY);
		final Map<Staff, Daily> dailyMap = getDailyMap(day);
		for (final Staff staff : staffs) {
			DailyData dailyData;
			if (dailyMap.containsKey(staff)) {
				dailyData = new DailyData(dailyMap.get(staff));
			} else {
				dailyData = newDailyData(staff, day);
			}
			dailyData.setEditPermission(isEditPermission(loginStaff, securityRole, staff));
			dailyList.add(dailyData);
		}
		return dailyList;
	}

	public void saveDaily(final Daily daily) {
		try {
			final TimeRange timeRange = TimeRange.valueOf(daily.getStartTime(), daily.getEndTime());
			daily.setStartTime(timeRange.getStartTime());
			daily.setEndTime(timeRange.getEndTime());
			final DailyLifecycle lifecycle = getLifecycleFactory().getLifecycle(DailyLifecycle.class);
			if (daily.getEntityId() != null) {
				lifecycle.update(daily, null);
			} else {
				lifecycle.create(daily);
			}
		} catch (IllegalArgumentException | OptimisticLockException e) {
			throw new BusinessException(e.getMessage());
		}
	}

	public Map<Staff, List<DailyData>> getDailyByPeriod(final Staff loginStaff, final List<Staff> staffList, final Date startDate, final Date endDate) {
		final Map<Staff, List<DailyData>> ret = getDailyByPeriod(staffList, startDate, endDate);
		final SecurityRole securityRole = getSecurityRole(loginStaff, Function.PERIOD);
		for (final List<DailyData> list : ret.values()) {
			for (final DailyData dailyData : list) {
				dailyData.setEditPermission(isEditPermission(loginStaff, securityRole, dailyData.getDaily().getStaff()));
			}
		}
		return ret;
	}

	public Map<Staff, List<DailyData>> getDailyByPeriod(final List<Staff> staffList, final Date startDate, final Date endDate) {
		final Map<Staff, List<DailyData>> ret = new HashMap<>();
		for (final Staff staff : staffList) {
			ret.put(staff, getDailyByPeriod(staff, startDate, endDate));
		}
		return ret;
	}

	public List<DailyData> getDailyByPeriod(final Staff staff, final Date startDate, final Date endDate) {
		final DailyLifecycle lifecycle = getLifecycleFactory().getLifecycle(DailyLifecycle.class);
		final List<Daily> list = lifecycle.findByPeriod(staff, startDate, endDate);
		final Map<Date, Daily> dailyMap = new HashMap<>();
		for (final Daily daily : list) {
			dailyMap.put(daily.getDate(), daily);
		}
		final List<DailyData> ret = new ArrayList<>();
		Date date = startDate;
		while (DateUtils.compareIgnoreTime(date, endDate) <= 0) {
			if (dailyMap.containsKey(date)) {
				ret.add(new DailyData(dailyMap.get(date)));
			} else {
				ret.add(newDailyData(staff, date));
			}
			date = DateUtils.getCalculateDayDate(date, 1);
		}
		return ret;
	}

	private boolean isEditPermission(final Staff loginStaff, final SecurityRole securityRole, final Staff staff) {
		final boolean editPermission = securityRole.compareTo(SecurityRole.ALPERSONAL) < 0 || staff.equals(loginStaff);
		return editPermission;
	}

	private SecurityRole getSecurityRole(final Staff loginStaff, final Function function) {
		final StaffGroupLifecycle staffGrouplifecycle = getLifecycleFactory().getLifecycle(StaffGroupLifecycle.class);
		return staffGrouplifecycle.findByStaffAndFunction(loginStaff, function);
	}

	private DailyData newDailyData(final Staff staff, final Date date) {
		final Daily e = new Daily();
		e.setDate(date);
		e.setStaff(staff);
		return new DailyData(e);
	}

	private Map<Staff, Daily> getDailyMap(final Date day) {
		final List<Daily> dailyList = getDailyByDay(day);
		final Map<Staff, Daily> dailyMap = new HashMap<>();
		for (final Daily daily : dailyList) {
			dailyMap.put(daily.getStaff(), daily);
		}
		return dailyMap;
	}

	private List<Daily> getDailyByDay(final Date date) {
		final DailyLifecycle lifecycle = getLifecycleFactory().getLifecycle(DailyLifecycle.class);
		return lifecycle.findByDay(date);
	}

}
